package org.creavi.engine.model.builder;

import org.creavi.engine.model.AdvancedKeyframeController;
import org.creavi.engine.model.JoinPointDefinition;
import org.creavi.engine.model.JoinPointPart;
import org.creavi.engine.model.MeshDefinition;
import org.creavi.engine.model.MeshPart;
import org.creavi.engine.model.ModelDefinition;
import org.creavi.engine.model.ModelInstance;

import com.jme.animation.SpatialTransformer;
import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jme.scene.SharedMesh;
import com.jme.scene.TriMesh;
import com.jmex.model.animation.KeyframeController;

public abstract class ModelInstanceBuilder {
	protected ModelInstance modelInstance;
	protected ModelDefinition modelDefinition;

	public ModelInstanceBuilder(ModelDefinition modelDefinition) {
		this.modelDefinition = modelDefinition;
	}

	public void createNewModelInstance(String name) {
		modelInstance = new ModelInstance(name, modelDefinition);
	}

	public ModelDefinition getModelDefinition() {
		return modelDefinition;
	}

	public void setModelDefinition(ModelDefinition modelDefinition) {
		this.modelDefinition = modelDefinition;
	}

	public ModelInstance getModelInstance() {
		return modelInstance;
	}

	public void buildBasicModel() {
		String name = modelInstance.getModelNode().getName();
		boolean adSet = false;
		for (MeshDefinition mesh : modelDefinition.getMeshes()) {
			TriMesh dynamic = new SharedMesh(name + "$dynMesh" + mesh.getId(),
					mesh.getKeyframes().get(0).getMesh());
			modelInstance.getModelNode().attachChild(dynamic);

			KeyframeController kfc = null;
			if (!adSet) {
				kfc = new AdvancedKeyframeController();
				adSet = true;
			} else {
				kfc = new KeyframeController();
			}
			kfc.setMorphingMesh(dynamic);
			kfc.setActive(false);

			for (MeshPart part : mesh.getKeyframes()) {
				kfc.setKeyframe(part.getKeyframe(), part.getMesh());
			}
			
			modelInstance.getKeyframeControllers().add(kfc);
		}

		SpatialTransformer st = new SpatialTransformer(modelDefinition
				.getJoinPoints().size());
		int joinIdx = 0;
		for (JoinPointDefinition join : modelDefinition.getJoinPoints()) {
			Node joinPoint = new Node(join.getName());

			st.setObject(joinPoint, joinIdx, -1);

			joinPoint.setLocalTranslation(join.getKeyframes().get(0)
					.getTranslation());
			joinPoint
					.setLocalRotation(join.getKeyframes().get(0).getRotation());
			joinPoint.setLocalScale(new Vector3f(1, 1, 1));

			for (JoinPointPart part : join.getKeyframes()) {
				st.setPosition(joinIdx, part.getKeyframe(), part
						.getTranslation());
				st.setRotation(joinIdx, part.getKeyframe(), part.getRotation());
				st.setScale(joinIdx, part.getKeyframe(), new Vector3f(1, 1, 1));
			}
			
			st.interpolateMissing();

			modelInstance.getModelNode().attachChild(joinPoint);
			joinIdx++;
		}

		modelInstance.setSpatialTransformer(st);
		modelInstance.getModelNode().addController(modelInstance);
	}

	public abstract void enhanceModel();
}
